package com.huilian.iotbox.admin.service.impl;

import com.huilian.iotbox.admin.service.OrderRefundService;
import com.huilian.iotbox.admin.service.UserService;
import com.huilian.iotbox.data.common.RedisKey;
import com.huilian.iotbox.data.common.ServerResponse;
import com.huilian.iotbox.data.config.AgencyConfig;
import com.huilian.iotbox.data.config.MiddlewareConfig;
import com.huilian.iotbox.data.dto.OrderRefundDto;
import com.huilian.iotbox.data.enums.FunctionEnum;
import com.huilian.iotbox.data.enums.RequestStatus;
import com.huilian.iotbox.data.enums.RoleEnum;
import com.huilian.iotbox.data.service.ErrorLogCommonService;
import com.huilian.iotbox.data.service.RefundService;
import com.huilian.iotbox.data.utils.HttpUtils;
import com.huilian.iotbox.data.utils.HttpsMain;
import com.huilian.iotbox.data.vo.UserInfo;
import com.huilian.iotbox.data.vo.UserVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.Serializable;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author 谢洛涛
 * @date 2021/7/15 16:11
 */
@Service
@Slf4j
public class OrderRefundServiceImpl implements OrderRefundService {
    @Resource
    private RedisTemplate<String, Serializable> redisCacheTemplate;
    @Autowired
    private ErrorLogCommonService errorLogCommonService;
    @Resource
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private UserService userService;
    @Resource
    private PasswordEncoder passwordEncoder;
    @Autowired
    private RefundService refundService;
    @Autowired
    private AgencyConfig agencyConfig;

    @Override
    public void queryOrderRefund() {
        Set<String> keys = redisCacheTemplate.keys("*" + RedisKey.ORDER_REFUND_ + "*");
        log.info("-----------------轮询退款订单状态查询-开始：{}-------------------", keys.size());
        OrderRefundDto item = null;
        for (String key : keys) {
            int index = key.indexOf(RedisKey.ORDER_REFUND_);
            key = key.substring(index);
            log.info("轮训订单key{}", key);
            try {
                item = (OrderRefundDto) redisCacheTemplate.opsForValue().get(key);
            } catch (Exception e) {
                e.printStackTrace();
                errorLogCommonService.writerInfoException("退款缓存查询失败", item, e);
            }
            if (item == null) {
                continue;
            }
            //查询退款订单
            try {
                Map<String, Object> form = new HashMap<>();
                form.put("HlMerchantId", item.getMerchantId());
                form.put("OutRefundNo", item.getOutRefundNo());
                String param = HttpUtils.format(agencyConfig, form, FunctionEnum.ORDER_REFUND_QUERY);
                String response = HttpsMain.httpsReq(MiddlewareConfig.orderUrl, param);
                log.info("请求响应结果{}", response);
                //延签并返回map值
                final Map<String, Object> result = HttpUtils.getResultData(response);
                final String status = (String) result.get("status");
                final String code = (String) result.get("code");
                if (status.equals(RequestStatus.SUCCESS.getCode()) && code.equals(RequestStatus.SUCCESS_CODE.getCode())) {
                    Map<String, String> resMap = (Map<String, String>) result.get("data");
                    OrderRefundDto orderRefundDto = new OrderRefundDto();
                    orderRefundDto.setOutRefundNo(resMap.get("outRefundNo"));
                    orderRefundDto.setOutTradeNo(resMap.get("outTradeNo"));
                    orderRefundDto.setRefundOrderNo(resMap.get("refundOrderNo"));
                    orderRefundDto.setTradeStatus(resMap.get("tradeStatus"));
                    orderRefundDto.setMerchantId(resMap.get("hlMerchantId"));
                    orderRefundDto.setRefundAmount(new BigDecimal(resMap.get("refundAmount")));
                    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    if (resMap.get("gmtRefundment") != null) {
                        orderRefundDto.setGmtRefundment(df.parse(resMap.get("gmtRefundment")));
                    }
                    if (!"refunding".equals(orderRefundDto.getTradeStatus())) {
                        log.info("申请退款成功后发送MQ：{}", System.currentTimeMillis());
                        CorrelationData correlationData = new CorrelationData(item.getRefundOrderNo());
                        rabbitTemplate.convertAndSend("iotBox-query-order-Refund", "iotBox-query-order-Refund.iotBoxQueryOrderRefund", orderRefundDto, correlationData);
                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
                errorLogCommonService.writerInfoException("查询退款订单异常", item, e);
            }
        }
        log.info("-----------------轮询退款订单状态查询-结束：-------------------");
    }


    @Override
    public ServerResponse refund(OrderRefundDto orderRefundDto, UserInfo userInfo) {
        if (StringUtils.isEmpty(orderRefundDto.getOperatePassword())) {
            return ServerResponse.createByErrorMessage("请输入操作密码");
        }
        if (StringUtils.isEmpty(orderRefundDto.getRefundReason())) {
            return ServerResponse.createByErrorMessage("请输入退款原因");
        }
        // 根据当前的订单号和当前操作的userId来校验密码是否正确
        UserVo userVo = new UserVo();
        if (RoleEnum.SUPER_ADMINISTRATOR.getRoleId().equals(userInfo.getRoleId())) {
            userVo = userService.getUserId(userInfo.getId());
        } else {
            userVo = userService.findOperatePasswordByOutTradeNoByUserId(orderRefundDto.getOutTradeNo(), userInfo.getId());
        }
        if (userVo == null) {
            return ServerResponse.createByErrorMessage("订单号有误，请重新提交或联系管理员");
        }
        boolean matches = passwordEncoder.matches(orderRefundDto.getOperatePassword(), userVo.getOperatePassword());
        if (!matches) {
            return ServerResponse.createByErrorMessage("操作密码不正确");
        }
        orderRefundDto.setOrderId(orderRefundDto.getOrderId());
        orderRefundDto.setOperatorId(userInfo.getId().toString());
        try {
            refundService.orderRefund(orderRefundDto);
        } catch (Exception e) {
            return ServerResponse.createByErrorMessage(e.getMessage());
        }
        return ServerResponse.createBySuccess("操作成功");
    }

}
